package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/bndr/gojenkins"
	"github.com/valyala/fasttemplate"
)

func CustomCreateFolder(ctx context.Context, jenkins gojenkins.Jenkins, id string, parents ...string) (*gojenkins.Folder, error) {
	folder, err := jenkins.GetFolder(ctx, id, parents...)

	if err != nil {
		//return nil, fmt.Errorf("trouble get folder: %v", err)
		fmt.Printf("err: %v\n", err)
	}
	if folder != nil {
		return folder, nil
	}

	folder2, err := jenkins.CreateFolder(ctx, id, parents...)

	if err != nil {
		return nil, fmt.Errorf("trouble create folder: %v", err)
	}

	return folder2, nil
}

// A task in queue will be assigned a build number in a job after a few seconds.
// this function will return the build object.
func CustomGetBuildFromQueueID(ctx context.Context, j *gojenkins.Jenkins, queueid int64, jobName string) (*gojenkins.Build, error) {
	task, err := j.GetQueueItem(ctx, queueid)
	if err != nil {
		return nil, err
	}
	// Jenkins queue API has about 4.7second quiet period
	for task.Raw.Executable.Number == 0 {
		time.Sleep(1000 * time.Millisecond)
		_, err = task.Poll(ctx)
		if err != nil {
			return nil, err
		}
	}

	buildid := task.Raw.Executable.Number
	//job, err := task.GetJob(ctx)
	job, err := j.GetJob(ctx, jobName)
	if err != nil {
		return nil, err
	}
	build, err := job.GetBuild(ctx, buildid)
	if err != nil {
		return nil, err
	}
	return build, nil
}

func CreateJavaPipleLineJob(ctx context.Context, jenkins gojenkins.Jenkins, projectId string, jobName string) (*gojenkins.Job, error) {
	template := `<?xml version='1.1' encoding='UTF-8'?>
	<flow-definition plugin="workflow-job">
	<actions/>
	<description>{{projectId}}-{{jobName}}</description>
	<keepDependencies>false</keepDependencies>
	<properties/>
	<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps">
	<script>
	
	pipeline {
		agent any

		tools {
			jdk 'JDK1.8'
			maven 'Maven3.9.5'
		}
		
		stages {
			stage('pull {{jobName}} code') {
				steps {
					git credentialsId: 'gitee', url: 'https://gitee.com/wz5891/jenkins-java-helloword.git'
				}
			}
			
			stage('build {{jobName}} code') {
				steps {
					sh 'mvn clean package'
				}
			}
		}
	}
	
	</script>
	<sandbox>true</sandbox>
	</definition>
	<triggers/>
	<disabled>false</disabled>
	</flow-definition>`

	t := fasttemplate.New(template, "{{", "}}")
	configString := t.ExecuteString(map[string]interface{}{
		"projectId": projectId,
		"jobName":   jobName,
	})

	job, err := jenkins.CreateJobInFolder(ctx, configString, jobName, projectId)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		//panic(err)

		return nil, err
	}

	if job != nil {
		log.Println("Job has been created in folder " + projectId)
	}

	return job, nil
}

func main() {
	projectId := "SpaceX"
	jobName := "server"

	// 连接Jenkins
	ctx := context.Background()
	//ctx := context.WithValue(context.Background(), "debug", 1)
	jenkins := gojenkins.CreateJenkins(nil, "http://127.0.0.1:8080/", "admin", "123456")
	_, err := jenkins.Init(ctx)

	if err != nil {
		log.Printf("连接Jenkins失败, %v\n", err)
		return
	}
	log.Println("Jenkins连接成功")

	folder, err := CustomCreateFolder(ctx, *jenkins, projectId)

	if err != nil {
		fmt.Printf("err: %v\n", err)
	}
	fmt.Printf("folder: %v\n", folder)

	job, err := CreateJavaPipleLineJob(ctx, *jenkins, projectId, jobName)

	if err != nil {
		fmt.Printf("err: %v\n", err)
		//panic(err)
	}

	if job != nil {
		log.Println("Job has been created in child folder")
	}

	log.Println("build job")
	//jenkins.BuildJob(ctx, jobName, nil)

	fmt.Printf("jobName: %v\n", projectId+"/job/"+jobName)

	realJobName := projectId + "/job/" + jobName

	queueid, err := jenkins.BuildJob(ctx, realJobName, nil)
	if err != nil {
		fmt.Printf("err: %v\n", err)

		panic(err)
	}
	fmt.Printf("queueid: %v\n", queueid)
	//build, err := jenkins.GetBuildFromQueueID(ctx, queueid)
	build, err := CustomGetBuildFromQueueID(ctx, jenkins, queueid, realJobName)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		panic(err)
	}

	// Wait for build to finish
	for build.IsRunning(ctx) {
		fmt.Printf("build.Raw.Executor: %v\n", build.Raw.Executor)
		time.Sleep(5000 * time.Millisecond)
		build.Poll(ctx)
	}

	fmt.Printf("build: %v\n", build)
	fmt.Printf("build number %d with result: %v\n", build.GetBuildNumber(), build.GetResult())
}
